package com.tian.view.draw.path

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.Rect
import android.graphics.RectF
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.tian.util.view.DisplayUtil

/**
 * @author tiansongtao, Email:769001510@qq.com
 * @date 2022/12/30 10:50
 *
 * path 绘制多个复合路径
 */
class PathView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
        View(context, attrs, defStyleAttr) {

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context) : this(context, null)

    val paint = Paint().apply {
        color = Color.RED
        strokeWidth = DisplayUtil.dpToPx(4f)
        style = Paint.Style.STROKE
    }
    val textPaint = Paint().apply {
        color = Color.BLACK
        style = Paint.Style.FILL_AND_STROKE
        textSize = DisplayUtil.spToPx(14f)
    }

    /**
     * [Path.reset]: 清空path数据，回归view左上角原点
     *
     * ---------- 绘制线 -----------
     * rXX: 都是相对于上个点的坐标的增量
     * 普通函数：都是相对于View左上角原点
     *
     * lineTo：画线到该坐标点, 相对于view左上角原点
     * rLineTo: 画线到该坐标点：相对于上个点的坐标
     *  eg: lineTo(10f,10f) rlineTo(10f,10f) 则第二个点相对于view左上角为 x=10+10，y=10+10
     *
     * moveTo, rMoveTo: 移动起始点到该坐标
     * setLastPoint: 更改最后一个点的坐标
     *
     * -------- 绘制常规图形 --------
     * 绘制常规图形 canvas也提供了方法，但Path也可以实现
     *
     * Direction: 方向， Path绘制图形可以控制绘制的方向
     *  [Path.Direction.CW] 顺时针方向绘制
     *  [Path.Direction.CCW] 逆时针方向绘制
     *
     *  [Path.addCircle]
     *  [Path.addRect]
     *  [Path.addRoundRect]
     *  [Path.addOval]
     *  [Path.addCircle]
     *  [Path.addArc]
     *  这个几个函数与canvas图形函数意思一致，
     *
     *  [Path.close]: 将起始点与终点连接，闭合形状
     *
     *  [Path.arcTo]: 画弧线，
     *      forceMoveTo: 主要是最后一个参数，是否将前一个结束点与现在的开始点连接起来
     *          false: 相当于增加了一个 lineTo
     *
     * [Path.FillType]: Path的填充模式
     *  [Path.FillType.WINDING] : 两个图形相交时取整个图形显示，包括相交的部分
     *  [Path.FillType.EVEN_ODD]: 两个图像相交时，不显示相交的部分, 只显示图形不相交那部分
     *  [Path.FillType.INVERSE_WINDING] : Inverse为相反的意思，会显示图形之外的
     *  [Path.FillType.INVERSE_EVEN_ODD] : 不显示图形不相交的那部分，其他的都会显示改颜色
     *
     * [Path.rewind] : reset不会清除[Path.setFillType], rewind会清除
     */
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val path = Path()
        path.lineTo(100f, 30f)
        path.lineTo(200f, 10f)
        path.rLineTo(100f, 20f)
        canvas.drawPath(path, paint)

        path.moveTo(10f, 20f)
        path.lineTo(80f, 40f)
        path.setLastPoint(70f, 50f)
        canvas.drawPath(path, paint)

        path.reset()
        path.addCircle(150f, 300f, 100f, Path.Direction.CW)
        canvas.drawPath(path, paint)
        /**
         * 在path路径上绘制文字
         * hOffset: 文字起始绘制位置与path起始位置距离
         * vOffeset: 文字离path路径的距离
         */
        canvas.drawTextOnPath("我们都是好孩子，最最善良的孩子", path, 100f, -10f, textPaint)

        path.reset()
        path.addCircle(150f, 600f, 100f, Path.Direction.CCW)
        canvas.drawPath(path, paint)
        /**
         * 在path路径上绘制文字
         * hOffset: 文字起始绘制位置与path起始位置距离
         * vOffeset: 文字离path路径的距离
         */
        canvas.drawTextOnPath("我们都是好孩子，最最善良的孩子", path, 100f, textPaint.textSize, textPaint)

        path.reset()
        val roundRectf = RectF(20f, 800f, 500f, 900f)
        val outerRadii = floatArrayOf(0f, 0f, 20f, 20f, 0f, 0f, 20f, 20f)
        path.addRoundRect(roundRectf, outerRadii, Path.Direction.CW)
        canvas.drawPath(path, paint)

        path.reset()
        path.moveTo(100f, 950f)
        path.lineTo(500f, 950f)
        path.lineTo(500f, 1200f)
        path.close()
        canvas.drawPath(path, paint)

        path.reset()
        path.moveTo(50f, 1250f)
        path.lineTo(500f, 1250f)
        val acrToRectf = RectF(50f, 1300f, 400f, 1600f)
        path.arcTo(acrToRectf, 0f, 180f, false)
        canvas.drawPath(path, paint)

        path.reset()
        path.addRect(500f, 100f, 700f, 300f, Path.Direction.CW)
        path.addCircle(700f, 300f, 100f, Path.Direction.CW)
        path.fillType = fillType
        paint.style = Paint.Style.FILL
        canvas.drawPath(path, paint)
        paint.style = Paint.Style.STROKE
    }


    var fillType = Path.FillType.WINDING
    var index = 0
    val rect = Rect(500, 100, 800, 400)

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            val x = event.x.toInt()
            val y = event.y.toInt()
            if (rect.contains(x, y)) {
                index++
                if (index > 3) {
                    index = 0
                }
                fillType = when (index) {
                    0 -> Path.FillType.WINDING
                    1 -> Path.FillType.EVEN_ODD
                    2 -> Path.FillType.INVERSE_WINDING
                    else -> Path.FillType.INVERSE_EVEN_ODD
                }
                invalidate()
                return true
            }
        }
        return super.onTouchEvent(event)
    }
}